﻿/*
 * LdRequestServerExtension.Modify
 * 
 * initial implementation : 26.6.2013
 * last upd: 27.9.2013
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see cz.uhul.DSMLv2.txt
 */
using System;
using cz.uhul.DSMLv2;


namespace cz.uhul.DSMLv2.Server.Sql
{



  public static partial class LdRequestServerExtension
  {




    public static LdModifyResponse Execute(this LdModifyRequest modReq)
    {

      LdDistinguishedName dn;
      bool isValid = true; //must be true here

      if (!LdDistinguishedName.TryParse(modReq.DistinguishedName, out dn))
        return new LdModifyResponse(
          LdResultCodeEnum.InvalidDNSyntax
          , "modifyRequest failed"
          , "invalid DistinguishedName:" + modReq.DistinguishedName
        );

      if (string.IsNullOrEmpty(dn))
        return new LdModifyResponse(
          LdResultCodeEnum.InvalidDNSyntax
          , "modifyRequest failed"
          , "invalid DN:[empty]"
        );

      //foreach (LdModifyAttr a in modReq.Attributes)
      //  if(a.Name.ToLower() == "objectclass")
      //    return new LdModifyResponse(
      //      LdResultCodeEnum.NamingViolation
      //      , "modifyRequest failed"
      //      , "can't modify objectClass:" + modReq.DistinguishedName
      //    );

      try
      {

        //foreach (LdModifyAttr a in modReq.Attributes)
        //  if (a.Operation == "replace")
        //    throw new NotImplementedException();

        foreach (LdModifyAttr a in modReq.Attributes)
        {
          if (a.Operation == LdAttrModifyOperationEnum.add)
            foreach (string val in a.Values)
              LdDatabase.AddAttrValue(modReq.DistinguishedName, a.Name, val);

              else if (a.Operation == LdAttrModifyOperationEnum.replace)
                //replace operation
                if (a.Values.Count == 1 && a.Values[0] != null)
                  //replace single value, do nothing then null as replacement...
                  LdDatabase.ReplaceSingleAttrValue(modReq.DistinguishedName, a.Name, a.Values[0]);

                else
                  //replace multi value
                  if (a.Values.Count % 2 != 0)
                    //Count of values must be an even number
                    throw new ArgumentException(
                      "can't replace multivalue with odd num of values, Values.Count = " + a.Values.Count.ToString()
                    );

                  else
                    for (int i = 0; i < a.Values.Count - 1; )
                      LdDatabase.ReplaceMultiAttrValue(
                        modReq.DistinguishedName
                        , a.Name, a.Values[i++].ToString()
                        , a.Values[i++].ToString()
                      );

              else
                //delete operation
                if (a.Values.Count == 0)
                  //delete all attribute values
                  isValid = LdDatabase.DeleteAllAttrValue(modReq.DistinguishedName, a.Name);

                else
                  //delete one of 
                  foreach (string val1 in a.Values)
                    isValid &= LdDatabase.DeleteAttrValue(modReq.DistinguishedName, a.Name, val1);
        }

        if (isValid)
          return new LdModifyResponse(LdResultCodeEnum.Success, "", "");

        else
          return new LdModifyResponse(
            LdResultCodeEnum.ConstraintViolation
            , "modifyRequest failed"
            , "invalid request, can't delete MUST attribute or db constraint violation, for:" + modReq.DistinguishedName
          );

      }
      catch (Exception e)
      {
        LdResultCodeEnum pickErr;

        if (e.Message.Contains("Can't insert duplicate key"))
          pickErr = LdResultCodeEnum.AttributeOrValueExists;

        else
          pickErr = LdResultCodeEnum.OperationsError;

        //todo:LdDatabase.DeleteEntry(RootDSE, DistinguishedName);
        //or better rollback tran
        return new LdModifyResponse(pickErr, "modifyRequest failed for:" + modReq.DistinguishedName, e.Message);
      }

    }





  }

}